/**
*====================================================
* 文件名称: MinaIoHandler.java
* 修订记录：
* No    日期				作者(操作:具体内容)
* 1.    2010-1-22			李自立(创建:创建文件)
*====================================================
* 类描述：(说明未实现或其它不应生成javadoc的内容)
* 
*/
package com.sunsharing.transport.mina;

import com.sunsharing.common.Constant;
import com.sunsharing.common.Context;
import com.sunsharing.common.ContextCreate;
import com.sunsharing.common.URL;
import com.sunsharing.common.config.Config;
import com.sunsharing.transport.Channel;
import com.sunsharing.transport.ConnectClients;
import com.sunsharing.transport.IoHandle;
import com.sunsharing.transport.LongChannel;
import org.apache.log4j.Logger;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import java.net.InetSocketAddress;
import java.util.Iterator;

/**
 *<pre><b><font color="blue">MinaIoHandler</font></b></pre>
 *
 *<pre><b>&nbsp;--描述说明--</b></pre>
 * <pre></pre>
 * <pre>
 * <b>--样例--</b>
 *   MinaIoHandler obj = new MinaIoHandler();
 *   obj.method();
 * </pre>
 * JDK版本：JDK1.5
 * @author  <b>李自立</b> 
 */
public class MinaIoHandler extends IoHandlerAdapter {

    IoHandle ioHandle;
    //是否客户端
    boolean client;
    URL url;

    public MinaIoHandler(IoHandle ioHandle, boolean client,URL url)
    {
        this.ioHandle = ioHandle;
        this.client = client;
        this.url = url;
    }

	
	/** 记录日志 */
	private static Logger logger = Logger.getLogger(MinaIoHandler.class);
	
	/**
	 * 有消息到达时被触发，message代表接收到的消息
	 * @param session 连接的session
	 * @param message 接收过来的信息
	 * @throws Exception  抛出的异常
	 */
	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {

        InetSocketAddress add = ((InetSocketAddress)session.getRemoteAddress());
        Context con = (Context)message;
        logger.info("收到报文:"+con.getMsg().msg);
        if(con.getMsgType()==Constant.MSG_TYPE_CONNECT)
        {
            MinaChannel channel = null;
            //收到客户端的汇报身份
            URL returnUrl =
                    LongChannel.initConnectURL(con.getMsg().msg,this.url,client,add.getHostName(),add.getPort());
            channel = new MinaChannel(session,returnUrl);
            channel.setIoHandle(ioHandle);
            Channel ch = ConnectClients.addClient(channel);
            ioHandle.doConnected(ch);
        }else if(con.getMsgType()==Constant.MSG_TYPE_HEART)
        {
            MinaChannel channel = (MinaChannel)searchChannelBySession(session);
            logger.error(client+"............."+channel);
            if(channel!=null)
            {
                logger.error(client + "收到心跳报文:" + channel.url);
                channel.refreshLastActiveTime();
                if(!client)
                {
                    //发回
                    logger.info(client + "发回心跳报文1:" + session);
                    channel.send(ContextCreate.createHeartContext());
                    //session.write(ContextCreate.createHeartContext());
                }
            }
        }else
        {
            if(client)
            {
                logger.info("收到报文:"+con.getMsg().msg);
            }
            MinaChannel channel = (MinaChannel)searchChannelBySession(session);
            channel.receive(con);
            channel.refreshLastActiveTime();
            //ioHandle.doRead(channel,(Context)message);
        }
	}

    @Override
    public void messageSent(org.apache.mina.core.session.IoSession session, java.lang.Object message)throws Exception{
        //InetSocketAddress add = ((InetSocketAddress)session.getRemoteAddress());
        //MinaChannel channel = (MinaChannel)clients.searchChannelBySession(session);
        //channel.s
        //ioHandle.doSend(channel,(Context)message);
    }
	
	/** 
	 * 当打开一个连接时被触发
	 * @param session 连接的session
	 * @throws Exception 抛出的异常
	 */
	@Override
	public void sessionOpened(IoSession session) throws Exception {
		logger.info("MINA已连接!"+ session.getRemoteAddress());
        MinaChannel channel = null;
        try
        {
            if(!client)
            {
                //只有服务端再发回确认状态
                session.write(ContextCreate.createConnectContext(url.toString()));
            }
        }catch (Exception e)
        {
             logger.error("处理出现异常",e);
        }finally {
            //clients.addClient(channel);
        }
	}
	
	/**
	 * 当一个连接关闭时被触发，即Session终止时被触发
	 * @param session 连接的session
	 * @throws Exception 抛出的异常
	 */
	@Override
	public void sessionClosed(IoSession session) throws Exception {
        MinaChannel channel = null;
        try
        {
            InetSocketAddress add = ((InetSocketAddress)session.getRemoteAddress());
            channel = (MinaChannel)searchChannelBySession(session);
            //ioHandle.doclose(channel);
        }catch (Exception e)
        {
            logger.error("关闭出现异常",e);
        } finally {
            ConnectClients.removeClient(channel);
        }
		logger.info("{}的连接已关闭!"+ session.getRemoteAddress());
	}
	
	/**
	 * 当连接空闲时被触发
	 * @param session 连接的session
	 * @param status 连接的状态
	 * @throws Exception 抛出的异常
	 */
	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        logger.info("server,idle:"+status);
	}

	
	/**
	 * 有异常发生时被触发
	 * @param session 连接的session
	 * @param cause 所有错误和异常类的父类Throwable
	 * @throws Exception 抛出的异常
	 */
	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		logger.error("异常:",cause);
	}

    public Channel searchChannelBySession(IoSession s)
    {
        Channel rst = null;
        for(Iterator<Channel> iter = ConnectClients.activeClients.iterator();iter.hasNext();)
        {
            Channel c = (Channel)iter.next();

            if(c instanceof MinaChannel)
            {
                if(s==((MinaChannel)c).session)
                {

                    rst = c;
                }
            }
        }
        return rst;
    }

}
